/**
 @file sys_nalpm2.h

 @date 2011-11-07

 @version v2.0

*/
#ifndef _sys_nalpm2_H
#define _sys_nalpm2_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "sal_types.h"
#include "sal.h"
#include "ctc_const.h"
#include "../tsingma/sys_tsingma_trie.h"
#include "sys_usw_ipuc.h"
#include "sys_usw_chip.h"
#include "sys_usw_wb_common.h"

/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
#define LEVEL0 0
#define LEVEL1 1
#define LEVELN 2
#define NALPM2_LN_EN(lchip) (g_sys_nalpm2_master[lchip]->multi_lvl_en)
#define PRE_LN(ln) ((ln > LEVEL0) ? (ln - 1) : LEVEL0)

#define LEVEL0_REC_CNT 5

#define NALPM2_FMT_V4 0
#define NALPM2_FMT_V6_64 1
#define NALPM2_FMT_V6_128 2
#define NALPM2_FMT_MAX 3

#define MERGE_OK 0
#define MERGE_NO_RESOURCE 1

#define COMPACT_DATA_BIT_NUM 72

#define SYS_NALPM2_V4_MASK_LEN_MAX 32/* 0-32 */
#define SYS_NALPM2_V6_MASK_LEN_MAX 128/* 0-32 */

#define SYS_NALPM2_PREFIX_LEN_INVALID (-1)/* -1 */
#define SYS_NALPM2_PREFIX_LEN_MIN 0/* 0*/
#define SYS_NALPM2_PREFIX_LEN_MAX 98/* ipv4:0-32; ipv6:0-64, MAX*/
#define SYS_NALPM2_PREFIX_LEN_V6_BASE 33/* ipv6-64 base:33*/
#define SYS_NALPM2_PREFIX_LEN_128_MAX 129/* 0-128, MAX*/

#define SYS_NALPM2_VRFID_MAX 256/* max vrf */
#define SYS_NALPM2_VRFID_DEF 0/* default vrf */

#define _MAX_KEY_LEN_32_ (32)
#define _MAX_KEY_LEN_128_ (128)
#define INVALID_DRV_NEXTHOP_OFFSET 0x3FFFF
#define INVALID_DRV_NEXTHOP_OFFSET_L0 0x3FFFE
#define INVALID_NEXTHOP_OFFSET 0xFFFF

#define SYS_NALPM2_MAX_SNACKE_L0 4
#define SYS_NALPM2_MAX_SNACKE_L1 8

#define ROUTE_NUM_PER_SNAKE_V4_L0 4
#define ROUTE_NUM_PER_SNAKE_V4_L1 6

#define SYS_NALPM2_MAX_SNAKE 8
#define ROUTE_NUM_PER_SNAKE_V4 6
#define ROUTE_NUM_PER_SNAKE_V6_64 3
#define ROUTE_NUM_PER_SNAKE_V6_128 2
#define ROUTE_NUM_PER_SNAKE_V6_COMPACT 4

#define MAX(a, b) (((a)>(b))?(a):(b))
#define MIN(a, b) (a < b ? a : b)

#define NALPM2_FORMAT(lchip, ip_ver) ((ip_ver == CTC_IP_VER_6)?(g_sys_nalpm2_master[lchip]->use_snake64?NALPM2_FMT_V6_64:NALPM2_FMT_V6_128):NALPM2_FMT_V4)

/* Macro of Bucket */
#define SYS_NALPM2_MAX_SUB_BUCKT 4
#define NALPM2_BUCKET_BSIZE 256

#define NALPM2_BUCKET_L0(lchip) g_sys_nalpm2_master[lchip]->bkt_l0
#define NALPM2_BUCKET_L1(lchip) g_sys_nalpm2_master[lchip]->bkt_l1

#define NALPM2_SNAKE_TABLE_L0(lchip, gid, type) NALPM2_BUCKET_L0(lchip).tbl_id[gid][type]
#define NALPM2_SNAKE_TABLE_L1(lchip, gid, type) NALPM2_BUCKET_L1(lchip).tbl_id[gid][type]

#define NALPM2_BUCKET_ARRAY_L0(lchip, bkt_idx) NALPM2_BUCKET_L0(lchip).bucket[bkt_idx/NALPM2_BUCKET_BSIZE][bkt_idx%NALPM2_BUCKET_BSIZE]
#define NALPM2_BUCKET_ARRAY_L1(lchip, bkt_idx) NALPM2_BUCKET_L1(lchip).bucket[bkt_idx/NALPM2_BUCKET_BSIZE][bkt_idx%NALPM2_BUCKET_BSIZE]

#define NALPM2_BUCKET_USE_LIST_L0(lchip, cnt)  NALPM2_BUCKET_L0(lchip).bkt_use_list[cnt]
#define NALPM2_BUCKET_USE_LIST_L1(lchip, cnt)  NALPM2_BUCKET_L1(lchip).bkt_use_list[cnt]

#define NALPM2_BUKCET_SNACK_PER_GRP_L0(lchip) NALPM2_BUCKET_L0(lchip).snake_per_group
#define NALPM2_BUKCET_SNACK_PER_GRP_L1(lchip) NALPM2_BUCKET_L1(lchip).snake_per_group

#define NALPM2_BUKCET_SNAKE_NUM_L0(lchip) (NALPM2_BUCKET_L0(lchip).snake_per_group*NALPM2_BUCKET_L0(lchip).snake_group_num)
#define NALPM2_BUKCET_SNAKE_NUM_L1(lchip) (NALPM2_BUCKET_L1(lchip).snake_per_group*NALPM2_BUCKET_L1(lchip).snake_group_num)

#define NALPM2_BUCKET_FMT_MAX_L0(lchip, fmt) (NALPM2_BUKCET_SNAKE_NUM_L0(lchip)*NALPM2_BUCKET_L0(lchip).snake_fmt_num[fmt])
#define NALPM2_BUCKET_FMT_MAX_L1(lchip, fmt) (NALPM2_BUKCET_SNAKE_NUM_L1(lchip)*NALPM2_BUCKET_L1(lchip).snake_fmt_num[fmt])

#define NALPM2_BUCKET_MAX_ENTRY_L0(lchip) NALPM2_BUCKET_FMT_MAX_L0(lchip, NALPM2_FMT_V4)
#define NALPM2_BUCKET_MAX_ENTRY_L1(lchip) NALPM2_BUCKET_FMT_MAX_L1(lchip, NALPM2_FMT_V4)

#define NALPM2_BUCKET_SUB_BKT_L0(lchip, bkt_idx) NALPM2_BUCKET_ARRAY_L0(lchip, bkt_idx).sub_bkt
#define NALPM2_BUCKET_SUB_BKT_L1(lchip, bkt_idx) NALPM2_BUCKET_ARRAY_L1(lchip, bkt_idx).sub_bkt

#define NALPM2_BUCKET_USE_CNT_L0(lchip, bkt_idx) NALPM2_BUCKET_ARRAY_L0(lchip, bkt_idx).use_cnt
#define NALPM2_BUCKET_USE_CNT_L1(lchip, bkt_idx) NALPM2_BUCKET_ARRAY_L1(lchip, bkt_idx).use_cnt

#define NALPM2_BUKCET_DB_SNAKE_NUM(lchip, ln, sram_type) (_sys_nalpm2_get_bucket_snake_cnt(lchip, ln, sram_type))

#define NALPM2_HW_SRAM_INDEX_L0(lchip, sram_index, snake_idx) (sram_index + (snake_idx % NALPM2_BUKCET_SNACK_PER_GRP_L0(lchip)) * NALPM2_BUCKET_L0(lchip).bkt_depth)
#define NALPM2_HW_SRAM_INDEX_L1(lchip, sram_index, snake_idx) (sram_index + (snake_idx % NALPM2_BUKCET_SNACK_PER_GRP_L1(lchip)) * NALPM2_BUCKET_L1(lchip).bkt_depth)

/* pfx is ipv4_value; pfx_len is valid bits number */
#define NALPM2_PFX2BITS(pfx, pfx_len, bit_str) \
{\
    int32 i = 0;\
    if (0 == pfx_len)\
    {\
        bit_str[0] = '0';\
    }\
    while (i < pfx_len)\
    {\
        if (pfx & (1 << i))\
        {\
            bit_str[pfx_len - 1 - i] = '1';\
        }\
        else\
        {\
            bit_str[pfx_len - 1 - i] = '0';\
        }\
        i++;\
    }\
}

#define SYS_IP_V6_SORT(val)           \
{                                          \
    if (CTC_IP_VER_6 == (val)->ip_ver)      \
    {                                      \
        uint32 t;                          \
        t = val->ip[0];               \
        val->ip[0] = val->ip[3]; \
        val->ip[3] = t;               \
                                       \
        t = val->ip[1];               \
        val->ip[1] = val->ip[2]; \
        val->ip[2] = t;               \
    }                                      \
}

#define SYS_IPV6_IP_SORT(ip_ver, ip)           \
{                                          \
    if (CTC_IP_VER_6 == ip_ver)      \
    {                                      \
        uint32 t;                          \
        t = ip[0];               \
        ip[0] = ip[3]; \
        ip[3] = t;               \
        t = ip[1];               \
        ip[1] = ip[2]; \
        ip[2] = t;               \
    }                                      \
}

#define NALPM2_GEN_IP_STR(buf, ip_ver, ip, mask) do{\
    char buf2[20] = {0};\
    sal_sprintf(buf2, "/%d", mask);\
    if(ip_ver == CTC_IP_VER_4)\
    {\
        uint32 tempip = sal_ntohl(ip[0]);\
        sal_inet_ntop(AF_INET, &tempip, buf, CTC_IPV6_ADDR_STR_LEN);\
        sal_strncat(buf, buf2, 5);\
    }\
    else\
    {\
    uint32 ipv6_address[4] = {0, 0, 0, 0};\
    ipv6_address[0] = sal_ntohl(ip[3]);\
    ipv6_address[1] = sal_ntohl(ip[2]);\
    ipv6_address[2] = sal_ntohl(ip[1]);\
    ipv6_address[3] = sal_ntohl(ip[0]);\
    sal_inet_ntop(AF_INET6, ipv6_address, buf, CTC_IPV6_ADDR_STR_LEN);\
        sal_strncat(buf, buf2, 5);\
    }\
}while(0);

#define NALPM2_INFO_SIZE(ver) \
((ver == CTC_IP_VER_4) ? (sizeof(sys_nalpm2_info_t) + sizeof(ip_addr_t)) : (sizeof(sys_nalpm2_info_t) + sizeof(ipv6_addr_t)))

#define IP_ADDR_SIZE(ver) \
((ver == CTC_IP_VER_4) ? (sizeof(ip_addr_t)) : (sizeof(ipv6_addr_t)))

#define SYS_NALPM2_INIT_CHECK \
    if(!g_sys_nalpm2_master[lchip])\
    {\
        return CTC_E_NOT_INIT;\
    }\

#define SYS_NALPM2_IP_ADDR_MASK(ip, len, ver)      \
    {                                           \
        if (CTC_IP_VER_4 == (ver))               \
        {                                       \
            IPV4_MASK((ip[0]), (len));        \
        }                                       \
        else                                    \
        {                                       \
            IPV6_MASK((ip), (len));        \
        }                                       \
    }

#define __________________ENUM__________________

enum sys_nalpm2_sram_entry_type_e {
    SYS_NALPM2_SRAM_TYPE_VOID,
    SYS_NALPM2_SRAM_TYPE_V4_32, /* 56bits, 6 * 2*/
    SYS_NALPM2_SRAM_TYPE_V6_64, /* 90bits, 3 * 2*/
    SYS_NALPM2_SRAM_TYPE_V6_128,/* 154bits, 2 * 2*/
    SYS_NALPM2_SRAM_TYPE_RESERVED,
    SYS_NALPM2_SRAM_TYPE_V4_EXT,
    SYS_NALPM2_SRAM_TYPE_MAX
};
typedef enum sys_nalpm2_sram_entry_type_e sys_nalpm2_sram_entry_type_t;

#define __________________SoftTable__________________

struct sys_nalpm2_info_s
{
    uint32 ad_idx;
    uint32 ip_ver          : 8;
    uint32 route_masklen   : 8;
    uint32 tcam_masklen    : 8;
    uint32 rsv             : 8;
    uint16 vrf_id;
    uint8 hw_position[2];
    struct sys_nalpm2_l0_item_s*   p_l0_item;
    uint32 ip[0];                     /* (ver == CTC_IP_VER_4) ? sizeof(ip_addr_t) : sizeof(ipv6_addr_t) */
};
typedef struct sys_nalpm2_info_s sys_nalpm2_info_t;

struct sys_nalpm2_tcam_item_s {
    sys_nalpm2_info_t*      p_l0_root_info;     /* prefix info*/
    sys_ipuc_info_t*        p_l0_root_AD;
    sys_nalpm2_info_t*      p_l0_info_array[SYS_NALPM2_MAX_SNACKE_L0][ROUTE_NUM_PER_SNAKE_V4_L0];
    trie_t* trie;                              /* sys_nalpm2_trie_l0_info_t */

    uint32 tcam_idx        : 16;
    uint32 sram_idx        : 16;

    uint32 sram_type       : 4;                /* indicate entry is v4_32, v6_64, or v6_128 */
    uint32 sub_bkt         : 3;
    uint32 rsv             : 25;
};
typedef struct sys_nalpm2_tcam_item_s sys_nalpm2_tcam_item_t;

struct sys_nalpm2_l0_item_s {
    sys_nalpm2_tcam_item_t* p_tcam_item;        /* point to prev level pivot */
    sys_nalpm2_info_t*      p_l1_root_info;     /* prefix info*/
    sys_ipuc_info_t*       p_l1_root_AD;
    sys_ipuc_info_t*       p_l1_info_array[SYS_NALPM2_MAX_SNACKE_L1][ROUTE_NUM_PER_SNAKE_V4_L1];
    trie_t *trie;                              /* sys_nalpm2_trie_l1_info_t */

    uint32 tcam_idx        : 16;               /* del */
    uint32 sram_idx        : 16;

    uint32 sram_type       : 4;                /* indicate entry is v4_32, v6_64, or v6_128 */
    uint32 sub_bkt         : 3;
    uint32 rsv             : 25;
};
typedef struct sys_nalpm2_l0_item_s sys_nalpm2_l0_item_t;

struct sys_nalpm2_trie_tcam_item_s {
    trie_node_t node;
    sys_nalpm2_tcam_item_t tcam_item;
};
typedef struct sys_nalpm2_trie_tcam_item_s sys_nalpm2_trie_tcam_item_t;

struct sys_nalpm2_trie_l0_item_s {
    trie_node_t node;
    sys_nalpm2_l0_item_t l0_item;
};
typedef struct sys_nalpm2_trie_l0_item_s sys_nalpm2_trie_l0_item_t;

struct sys_nalpm2_trie_l0_info_s {
    trie_node_t node;                 /*trie node: used to store payload on trie */
    sys_nalpm2_info_t* p_l0_info;
};
typedef struct sys_nalpm2_trie_l0_info_s sys_nalpm2_trie_l0_info_t;

struct sys_nalpm2_trie_l1_info_s {
    trie_node_t node;                 /*trie node: used to store payload on trie */
    sys_ipuc_info_t* p_l1_info;
};
typedef struct sys_nalpm2_trie_l1_info_s sys_nalpm2_trie_l1_info_t;

struct sys_nalpm2_bucket_l0_s {
    ctc_list_pointer_node_t node;
    sys_nalpm2_tcam_item_t* p_tcam_item[SYS_NALPM2_MAX_SUB_BUCKT];
    uint8 bitmap[SYS_NALPM2_MAX_SNAKE];
    uint32 sram_idx    : 16;
    uint32 use_cnt     : 16;
    uint32 fmt         : 8;
    uint32 sub_bkt     : 8;
    uint32 is_root     : 1;
    uint32 rsv         : 15;
};
typedef struct sys_nalpm2_bucket_l0_s sys_nalpm2_bucket_l0_t;

struct sys_nalpm2_bucket_l1_s {
    ctc_list_pointer_node_t node;
    sys_nalpm2_l0_item_t* p_l0_item[SYS_NALPM2_MAX_SUB_BUCKT];
    uint8 bitmap[SYS_NALPM2_MAX_SNAKE];
    uint32 sram_idx    : 16;
    uint32 use_cnt     : 16;
    uint32 fmt         : 8;
    uint32 sub_bkt     : 8;
    uint32 is_root     : 1;
    uint32 rsv         : 15;
};
typedef struct sys_nalpm2_bucket_l1_s sys_nalpm2_bucket_l1_t;

struct sys_nalpm2_bkt_l0_s {
    ctc_list_pointer_t* bkt_use_list;
    sys_nalpm2_bucket_l0_t** bucket;
    uint32 tbl_id[2][SYS_NALPM2_SRAM_TYPE_MAX];
    uint32 bkt_usage[NALPM2_FMT_MAX];
    uint8 snake_fmt_num[NALPM2_FMT_MAX];
    uint32 real_bkt_depth;
    uint32 bkt_depth;
    uint32 bkt_cnt;
    uint32 snake_per_group  : 8;
    uint32 snake_group_num  : 8;
    uint32 rsv              : 8;
};
typedef struct sys_nalpm2_bkt_l0_s sys_nalpm2_bkt_l0_t;

struct sys_nalpm2_bkt_l1_s {
    ctc_list_pointer_t* bkt_use_list;
    sys_nalpm2_bucket_l1_t** bucket;
    uint32 tbl_id[2][SYS_NALPM2_SRAM_TYPE_MAX];
    uint32 bkt_usage[NALPM2_FMT_MAX];
    uint8 snake_fmt_num[NALPM2_FMT_MAX];
    uint32 real_bkt_depth;
    uint32 bkt_depth;
    uint32 bkt_cnt;
    uint32 snake_per_group  : 8;
    uint32 snake_group_num  : 8;
    uint32 rsv              : 8;
};
typedef struct sys_nalpm2_bkt_l1_s sys_nalpm2_bkt_l1_t;

typedef void (* sys_nalpm2_build_l1_snake_cb_t)(sys_nalpm2_l0_item_t* p_l0_item, sys_ipuc_info_t* p_l1_info, uint8 entry_idx, uint8 is_update, void* p_ds_data, void* p_ds_mask);

typedef struct sys_nalpm2_cookie_s sys_nalpm2_cookie_t;
struct sys_nalpm2_master_s {
    trie_t **prefix_trie[LEVELN][MAX_CTC_IP_VER];
    trie_t **route_db_trie[MAX_CTC_IP_VER];
    ctc_hash_t* ipuc_cover_hash[LEVELN];
    ctc_hash_t* pivot_hash[LEVELN];
    uint32 *vrf_route_cnt[MAX_CTC_IP_VER];
    sys_nalpm2_build_l1_snake_cb_t    build_l1_snake_cb[SYS_NALPM2_SRAM_TYPE_MAX];  
    sys_nalpm2_bkt_l0_t bkt_l0;
    sys_nalpm2_bkt_l1_t bkt_l1;
    uint32 len2pfx[SYS_NALPM2_V4_MASK_LEN_MAX+1];
    uint32 ln_entry_cnt[LEVELN][MAX_CTC_IP_VER];
    uint32 route_stats[MAX_CTC_IP_VER][MAX_STATS_TYPE];
    uint8 frag_arrange_status[MAX_CTC_IP_VER];
    uint32 merge_cnt;
    uint8 opf_type_nalpm;
    uint8 ipsa_enable;
    uint8 use_snake64;
    uint8 frag_arrange_enable;
    uint8 split_mode;
    uint8 bucket_num;
    uint8 ipv6_couple_mode;
    uint8 move_hit_en;

    sys_nalpm2_cookie_t* p_cookie_split_l1;                     /* solve l0 route cover recursion issue */
    sys_nalpm2_cookie_t* p_cookie_covered_l1;                   /* solve l0 route cover recursion issue */
};
typedef struct sys_nalpm2_master_s sys_nalpm2_master_t;

#define __________________TempStruct__________________

struct sys_nalpm2_info_tmp_s
{
    sys_nalpm2_info_t nalpm2_info;
    uint32 ip[4];                     /* (ver == CTC_IP_VER_4) ? sizeof(ip_addr_t) : sizeof(ipv6_addr_t) */
};
typedef struct sys_nalpm2_info_tmp_s sys_nalpm2_info_tmp_t;

struct sys_nalpm2_route_store_info_s {
    uint8 tcam_hit;
    uint8 sram_hit[2];       /* sram_hit[0]:L0;sram_hit[1]:L1; */
    uint8 snake_idx[2];      /* snake_idx[0]:L0;snake_idx[1]:L1; */
    uint8 entry_offset[2];  /*route idx in one snake*/ /* entry_offset[0]:L0;entry_offset[1]:L1; */
    uint8 total_skip_len;
    sys_nalpm2_tcam_item_t* p_tcam_item;
    sys_nalpm2_l0_item_t* p_l0_item;
};
typedef struct sys_nalpm2_route_store_info_s sys_nalpm2_route_store_info_t;

struct sys_nalpm2_route_and_lchip_s
{
    sys_nalpm2_info_t* p_l0_info;
    sys_ipuc_info_t* p_l1_info;
    trie_node_t* p_father;
    uint32 prefix_len;
    uint32 nh_id;
    uint8 origin_lchip;
    uint8 ageing_opt; /*1 set, 2 get*/
    uint8 ageing_bit;
    uint8 is_covered;
    uint8 lchip;
};
typedef struct sys_nalpm2_route_and_lchip_s sys_nalpm2_route_and_lchip_t;

struct sys_nalpm2_route_cover_trav_s
{
    void* ptr1;
    void* ptr2;
    void* ptr3;
    void* ptr4;
    uint32 value1;
    uint32 value2;
};
typedef struct sys_nalpm2_route_cover_trav_s  sys_nalpm2_route_cover_trav_t;

struct sys_nalpm2_route_key_s
{
    uint16 vrfid;
    uint8 ip_ver;
    uint8 masklen;
    union
    {
        ip_addr_t ipv4;
        ipv6_addr_t ipv6;
    } ip;
};
typedef struct sys_nalpm2_route_key_s sys_nalpm2_route_key_t;

struct sys_nalpm2_dump_route_info_s
{
    sys_nalpm2_info_t* p_nalpm_info;
    uint16 index;
    uint8 detail;
    uint8 mode;
};
typedef struct sys_nalpm2_dump_route_info_s sys_nalpm2_dump_route_info_t;

struct sys_nalpm2_cookie_s
{
    sys_nalpm2_tcam_item_t* p_install_tcam;
    sys_nalpm2_l0_item_t* p_install_l0;

    sys_nalpm2_tcam_item_t* p_chd_tcam;
    sys_nalpm2_l0_item_t* p_chd_l0;

    sys_nalpm2_l0_item_t* p_splited_l0; /* for l0 route cover, compare covered */
    sys_nalpm2_l0_item_t* p_new_l0; /* for l1 route cover after l0 cover*/

    sys_nalpm2_info_t* p_l0_info_new;
    sys_ipuc_info_t* p_l1_info_new;

    uint32 ds_snake_new[SYS_NALPM2_MAX_SNAKE][12];
    uint32 ds_snake_new_mask[SYS_NALPM2_MAX_SNAKE][12];
    uint32 ds_snake[SYS_NALPM2_MAX_SNAKE][12];
    uint32 ds_snake_mask[SYS_NALPM2_MAX_SNAKE][12];

    uint16 clear_array[SYS_NALPM2_MAX_SNAKE*ROUTE_NUM_PER_SNAKE_V4];
    uint16 index_array[SYS_NALPM2_MAX_SNAKE*ROUTE_NUM_PER_SNAKE_V4];

    uint8 clear_cnt;
    uint8 split_cnt;

    uint8 new_tcam;
    uint8 merge_cnt;
    uint8 cur_idx;

    uint8 route_in_new_trie;
    uint8 new_route_moved;/* new route in old trie,but move after l0 route cover */
    uint8 is_new_trie;

    uint8 lchip;
    uint8 ln;

    uint16 old_sram_idx_l1; /* only use when proccess l0 cover */
    uint16 new_sram_idx_l1; /* only use when proccess l0 cover */
    uint8 need_free; /* only use when proccess l0 cover */
};

struct sys_nalpm2_tcam_ad_s {
    uint32 tcam_idx;

    uint32 ip[4];
    uint32 masklen;
};
typedef struct sys_nalpm2_tcam_ad_s sys_nalpm2_tcam_ad_t;

struct sys_nalpm2_l0_ad_s {
    uint16 sram_idx;
    uint8 snake_idx;
    uint8 entry_offset;
    uint8 sram_type;    //???

    uint32 ip[4];
    uint32 masklen;
};
typedef struct sys_nalpm2_l0_ad_s sys_nalpm2_l0_ad_t;

#if 0
typedef struct _alpm_cb_merge_ctrl_s {
    uint8 lchip;
    uint32 merge_count;
    uint32 vrf_id;
    uint8 ip_ver;
    uint8 bnk_pbkt;
    uint32 ent_pbnk;
    uint32 prefix[4];
    uint8  prefix_len[4];
    uint32 max_cnt;
    uint32 sram_idx;
}sys_alpm_cb_merge_ctrl_t;
#endif

#define __________________Declaration__________________

int32
_sys_nalpm2_route_cmp_l0(uint8 lchip, sys_nalpm2_info_t* p_route_info_0, sys_nalpm2_info_t* p_route_info_1);

int32
_sys_nalpm2_route_cmp_l1(uint8 lchip, sys_ipuc_info_t* p_route_info_0, sys_ipuc_info_t* p_route_info_1);

uint8
_sys_nalpm2_root_mask_cmp_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_route_match_l0(uint8 lchip, sys_nalpm2_info_t* p_l0_root_info, sys_nalpm2_info_t* p_l0_info);

int32
_sys_nalpm2_route_match_l1(uint8 lchip, sys_nalpm2_info_t* p_l1_root_info, sys_ipuc_info_t* p_l1_info);

uint8
_sys_nalpm2_get_snake_route_num_l0(uint8 lchip, uint8 sram_type);

uint8
_sys_nalpm2_get_snake_route_num_l1(uint8 lchip, uint8 sram_type);

uint8
_sys_nalpm2_get_snake_bitwdith(uint8 lchip, uint8 sram_type);

uint8
_sys_nalpm2_get_node_num(uint8 lchip, uint8 sram_type);

int32
_sys_nalpm2_get_table_id_l0(uint8 lchip, uint8 type, uint8 snake_idx, uint32* p_tbl_id, uint32* p_tbl_id1);

int32
_sys_nalpm2_get_table_id_l1(uint8 lchip, uint8 type, uint8 snake_idx, uint32* p_tbl_id, uint32* p_tbl_id1);

int32
_sys_nalpm2_lkup_entry_l0(uint8 lchip, sys_nalpm2_info_t* p_l0_info, sys_nalpm2_route_store_info_t* p_lkp_rlt, sys_nalpm2_tcam_item_t *p_tcam_item);

int32
_sys_nalpm2_lkup_entry_l1(uint8 lchip, sys_ipuc_info_t* p_l1_info, sys_nalpm2_route_store_info_t* p_lkp_rlt, sys_nalpm2_l0_item_t* p_l0_item);

int32
_sys_nalpm2_route_lkp_l0(uint8 lchip, sys_nalpm2_info_t* p_nalpm_info, sys_nalpm2_route_store_info_t* p_lkp_rlt);

int32
_sys_nalpm2_route_lkp_l1(uint8 lchip, sys_nalpm2_info_t* p_nalpm_info, sys_nalpm2_route_store_info_t* p_lkp_rlt);

int32
_sys_nalpm2_sram_entry_is_full_l0(uint8 lchip, sys_nalpm2_tcam_item_t *p_tcam_item, uint8 new_root);

int32
_sys_nalpm2_sram_entry_is_full_l1(uint8 lchip, sys_nalpm2_l0_item_t *p_l0_item);

int32
_sys_nalpm2_search_best_route_in_sram_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_info_t* p_l0_root_info, sys_nalpm2_info_t** pp_best_route);

int32
_sys_nalpm2_search_best_route_in_sram_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_info_t* p_l1_root_info, sys_ipuc_info_t** pp_best_route);

int32
_sys_nalpm2_find_best_position_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, uint8 masklen, uint8* snake_idx, uint8* offset);

int32
_sys_nalpm2_find_best_position_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, uint8 masklen, uint8* snake_idx, uint8* offset);

int32
_sys_nalpm2_free_route_node_l0(trie_node_t* node, void *data);

int32
_sys_nalpm2_free_route_node_l1(trie_node_t* node, void *data);

int32
_sys_nalpm2_free_prefix_node_l0(trie_node_t * p_node, void * user_data);

int32
_sys_nalpm2_free_prefix_node_l1(trie_node_t * p_node, void * user_data);

int32
_sys_nalpm2_ipuc_hash_make_l0(sys_nalpm2_tcam_ad_t* p_tcam_ad);

int32
_sys_nalpm2_ipuc_hash_make_l1(sys_nalpm2_l0_ad_t* p_l0_ad);

int32
_sys_nalpm2_ipuc_hash_cmp_l0(sys_nalpm2_tcam_ad_t* p_tcam_ad_0, sys_nalpm2_tcam_ad_t* p_tcam_ad_1);

int32
_sys_nalpm2_ipuc_hash_cmp_l1(sys_nalpm2_l0_ad_t* p_l0_ad_0, sys_nalpm2_l0_ad_t* p_l0_ad_1);

int32
_sys_nalpm2_pivot_hash_make_l0(sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_pivot_hash_make_l1(sys_nalpm2_l0_item_t* p_l0_item);

int32
_sys_nalpm2_pivot_hash_cmp_l0(sys_nalpm2_tcam_item_t* p_db_tcam_item, sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_pivot_hash_cmp_l1(sys_nalpm2_l0_item_t* p_db_tcam_item, sys_nalpm2_l0_item_t* p_l0_item);

int32
_sys_nalpm2_tcam_idx_alloc(uint8 lchip, ctc_ipuc_param_t* p_ipuc_param, sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_tcam_idx_free(uint8 lchip, ctc_ipuc_param_t* p_ipuc_param, sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_write_tcam(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_ipuc_opt_type_t opt, uint32 update_ad_idx);

int32
_sys_nalpm2_read_tcam(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, uint32* p_ad_idx);

int32
_sys_nalpm2_sram_idx_share_l1(uint8 lchip, uint8 fmt, uint32* p_sram_idx);

int32
_sys_nalpm2_sram_idx_alloc_l0(uint8 lchip, uint8 ip_ver, uint16* p_sram_idx, uint8* sub_idx, uint8 is_root);

int32
_sys_nalpm2_sram_idx_alloc_l1(uint8 lchip, uint8  ip_ver, uint16* p_sram_idx, uint8* sub_idx, uint8 is_root);

int32
_sys_nalpm2_sram_idx_free_l0(uint8 lchip, uint16 sram_idx, uint8 ip_ver);

int32
_sys_nalpm2_sram_idx_free_l1(uint8 lchip, uint16 sram_idx, uint8 ip_ver);

int32
_sys_nalpm2_write_sram_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_info_t* p_l0_info, uint8 snake_idx, uint8 entry_idx, uint8 is_update, void* p_data, void* p_data_mask);

int32
_sys_nalpm2_write_sram_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_ipuc_info_t* p_l1_info, uint8 snake_idx, uint8 entry_idx, uint8 is_update, void* p_data, void* p_data_mask);

int32
_sys_nalpm2_set_sram_type_l0(uint8 lchip, uint8 ip_ver, uint8 router_mask_len, sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_set_sram_type_l1(uint8 lchip, uint8 ip_ver, uint8 router_mask_len, sys_nalpm2_l0_item_t* p_tcam_item);

int32
_sys_nalpm2_update_longer_pfx_AD_add(trie_node_t* p_longer_pfx_node,void* data);

int32
_sys_nalpm2_update_lvl0_longer_pfx_AD_add(trie_node_t* p_longer_pfx_node,void* data);

int32
_sys_nalpm2_add_route_cover(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_ipuc_info_t* p_l1_info, uint32 nh_id, uint32 total_skip_len, uint8 ageing_opt, uint8 *p_hit);

int32
_sys_nalpm2_update_longer_pfx_AD_del(trie_node_t* p_longer_pfx_node,void* data);

int32
_sys_nalpm2_update_lvl0_longer_pfx_AD_del(trie_node_t* p_longer_pfx_node, void* data);

int32
_sys_nalpm2_deletes_route_cover(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_ipuc_info_t* p_l1_info, uint32 total_skip_len);

int32
_sys_nalpm2_update_longer_pfx_AD_default(trie_node_t* p_longer_pfx_node, void* data);

int32
_sys_nalpm2_update_lvl0_longer_pfx_AD_default(trie_node_t* p_longer_pfx_node,void* data);

int32
_sys_nalpm2_default_route_cover(uint8 lchip,uint8 ip_ver, uint16 vrf_id, uint32 ad_index);

int32
_sys_nalpm2_default_lvl0_route_cover(uint8 lchip,uint8 ip_ver, uint16 vrf_id, uint32 ad_index);

int32
_sys_nalpm2_bucket_init_l0(uint8 lchip);

int32
_sys_nalpm2_bucket_init_l1(uint8 lchip);

int32
_sys_nalpm2_bucket_deinit_l0(uint8 lchip);

int32
_sys_nalpm2_bucket_deinit_l1(uint8 lchip);

int32
_sys_nalpm2_bucket_list_update_l0(uint8 lchip, uint16 sram_idx, int32 incr_cnt);

int32
_sys_nalpm2_bucket_list_update_l1(uint8 lchip, uint16 sram_idx, int32 incr_cnt);

int32
_sys_nalpm2_recreate_cookie(trie_node_t * node, void *data);

int32
_sys_nalpm2_create_cookie_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_tcam_item_t* p_tcam_item_new, sys_nalpm2_cookie_t** pp_cookie);

int32
_sys_nalpm2_create_cookie_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_l0_item_t* p_l0_item_new, sys_nalpm2_cookie_t** pp_cookie);

int32
_sys_nalpm2_write_route_cookie_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_tcam_item_t* p_tcam_item_new, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_write_route_cookie_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_l0_item_t* p_l0_item_new, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_route_install_element_l0(trie_node_t* node, void *data);

int32
_sys_nalpm2_route_install_element_l1(trie_node_t* node, void *data);

int32
_sys_nalpm2_reinstall_element_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_reinstall_element_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_alloc_offset_array_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_alloc_offset_array_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_renew_route_trie_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_cookie_t* p_cookie, uint8 new_tcam);

int32
_sys_nalpm2_renew_route_trie_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_cookie_t* p_cookie, uint8 new_tcam);

int32
_sys_nalpm2_clear_snake_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item);

int32
_sys_nalpm2_clear_snake_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item);

int32
_sys_nalpm2_ln_pivot_insert_l0(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_tcam_item_t** p_tcam_item);

int32
_sys_nalpm2_ln_pivot_insert_l1(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_l0_item_t** p_l0_item);

int32
_sys_nalpm2_ln_pivot_del_l0(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param);

int32
_sys_nalpm2_ln_pivot_del_l1(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param);

int32
_sys_nalpm2_add_directly_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_info_t* p_l0_info, sys_nalpm2_route_store_info_t *p_lkp_rlt);

int32
_sys_nalpm2_add_directly_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_ipuc_info_t* p_l1_info, sys_nalpm2_route_store_info_t *p_lkp_rlt);

int32
_sys_nalpm2_move_route_trie(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_info_t* p_best_route, sys_nalpm2_cookie_t* p_cookie);

int32
_sys_nalpm2_add_split_l0(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_l0_item_t* p_l0_item, sys_nalpm2_tcam_item_t** pp_new_tcam_item);

int32
_sys_nalpm2_add_split_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_l0_item_t** pp_l0_item_new);

int32
_sys_nalpm2_ln_insert_l0(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_l0_item_t *p_l0_item, uint8 new_root);

int32
_sys_nalpm2_ln_del_l0(uint8 lchip, ctc_ipuc_param_t* p_ipuc_param, sys_nalpm2_tcam_item_t* p_tcam_item, sys_nalpm2_l0_item_t* p_l0_item, uint8 is_inner);

int32
_sys_nalpm2_create_node_l1(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_route_store_info_t *p_lkp_rlt);

int32
_sys_nalpm2_destroy_node_l1(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_route_store_info_t *p_lkp_rlt);

int32
_sys_nalpm2_find_best_covered_node_l0(uint8 lchip, sys_nalpm2_route_store_info_t *p_lkp_rlt);

int32
_sys_nalpm2_find_best_covered_node_l0_2(uint8 lchip, sys_nalpm2_tcam_item_t* p_tcam_item_new, uint32 ad_idx);

int32
_sys_nalpm2_route_vrf_init(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param);

int32
_sys_nalpm2_route_vrf_deinit(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param);

extern int32
sys_nalpm2_init(uint8 lchip, ctc_ipuc_global_cfg_t* p_ipuc_global_cfg, uint8 ipsa_enable);

extern int32
sys_nalpm2_deinit(uint8 lchip);

extern int32
sys_nalpm2_add(uint8 lchip, void* p_sys_ipuc_param_v, uint32 ad_index, void* data);

extern int32
sys_nalpm2_del(uint8 lchip, void* p_sys_ipuc_param_v, void *p_lkp_rlt_inner);

extern int32
sys_nalpm2_update(uint8 lchip, void* p_sys_ipuc_param_v, uint32 ad_index);

int32
sys_nalpm2_enable_sram_idx_share(uint8 lchip, uint32 num, uint8 enable);

extern int32
sys_nalpm2_ageing_opt(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, uint8 opt, uint8 *p_hit);

extern int32
sys_nalpm2_auto_merge(uint8 lchip, uint8 enable);

extern int32
sys_nalpm2_set_fragment_status(uint8 lchip, uint8 ip_ver, uint8 status);

extern int32
sys_nalpm2_get_fragment_status(uint8 lchip, uint8 ip_ver, uint8* status);

extern int32
sys_nalpm2_get_fragment_auto_enable(uint8 lchip, uint8* enable);

extern int32
sys_nalpm2_move_hit_en(uint8 lchip, uint8 enable);

int32
_sys_nalpm2_dump_route_trie_node_l0(trie_node_t* node, void* data);

int32
_sys_nalpm2_dump_pfx_trie_node(trie_node_t* node, void* data);

int32
_sys_nalpm2_dump_route_l0(uint8 lchip, sys_nalpm2_info_t* p_l0_info);

int32
_sys_nalpm2_dump_route_l1(uint8 lchip, sys_ipuc_info_t* p_l1_info);

int32
_sys_nalpm2_dump_route_trie_l1(uint8 lchip, sys_nalpm2_l0_item_t* p_l0_item);

int32
_sys_nalpm2_dump_route_trie(trie_node_t* node, void* data);

extern int32
sys_nalpm2_show_route_info(uint8 lchip, void* p_ipuc_param_v);

extern int32
sys_nalpm2_show_sram_usage(uint8 lchip);

extern int32
sys_nalpm2_show_status(uint8 lchip);

extern int32
sys_nalpm2_dump_pfx_trie(uint8 lchip, uint16 vrfid, uint8 ip_ver);

extern int32
sys_nalpm2_dump_route_trie(uint8 lchip, uint16 index, ctc_ipuc_param_t* p_ipuc_param, uint8 mode, uint8 detail, uint16 vrf_max);

extern int32
sys_nalpm2_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param);

extern int32
sys_nalpm2_check_route(uint8 lchip, void *p_info, void* cb);

extern int32
sys_nalpm2_dump_db_route_trie(uint8 lchip, uint8 ip_ver, uint16 vrf_id);

void
_sys_nalpm2_wb_mapping_ad_l0(sys_nalpm2_tcam_item_t* p_tcam_item, sys_wb_nalpm_prefix_info_t* p_wb_prefix_info, sys_nalpm2_tcam_ad_t* p_tcam_ad, uint8 is_sync);

void
_sys_nalpm2_wb_mapping_ad_l1(sys_nalpm2_l0_item_t* p_l0_item, sys_wb_nalpm_pivot_info_t* p_wb_pivot_info, sys_nalpm2_l0_ad_t* p_l0_ad, uint8 is_sync);

int32
__sys_nalpm2_wb_ad_sync_l0(trie_node_t * p_node, void * user_data);

int32
__sys_nalpm2_wb_ad_sync_l1(trie_node_t * p_node, void * user_data);

int32
_sys_nalpm2_wb_ad_sync_l0(uint8 lchip, uint32 app_id, void *p_temp_wb_data);

int32
_sys_nalpm2_wb_ad_sync_l1(uint8 lchip, uint32 app_id, void *p_temp_wb_data);

int32
_sys_nalpm2_wb_restore_l0(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_info_t* p_nalpm_info);

int32
_sys_nalpm2_wb_restore_l1(uint8 lchip, sys_ipuc_param_t* p_sys_ipuc_param, sys_nalpm2_l0_item_t* p_l0_item);

int32
_sys_nalpm2_wb_ad_restore_l0(uint8 lchip);

int32
_sys_nalpm2_wb_ad_restore_l1(uint8 lchip);

int32
_sys_nalpm2_wb_traverse_route_trie(trie_node_t* node, void* data);

int32
_sys_nalpm2_wb_traverse_set_ad_l0(trie_node_t* node, void* data);

int32
_sys_nalpm2_wb_traverse_set_ad_l1(trie_node_t* node, void* data);

extern int32
sys_nalpm2_wb_set_tcam_index(uint8 lchip);

extern int32
sys_nalpm2_wb_set_ad_info(uint8 lchip);

int32
sys_nalpm2_wb_prefix_sync(uint8 lchip, uint32 app_id, void *p_temp_wb_data);

int32
sys_nalpm2_wb_prefix_restore(uint8 lchip);

#ifdef __cplusplus
}
#endif

#endif

